Reason across multiple entities

Reason across multiple entities

Using extended forms of the For, Exists and ForAll functions, you can reason across several different entities in a single rule. You can also reason with different instances of the same entity, and compare instances of the same entity.

What do you want to do?

Extend the For, For All and Exists functions

Use relationship membership as a rule input

Remove ambiguity when reasoning about more than one instance of the same entity 

Compare instances of the same entity

Extend the For, For All and Exists functions

Entity functions, such as For, Exists and For All, allow you to reason across a single relationship from a source entity to a target entity. If, however, you want to cross multiple relationships in a rule and reason against several entities in that rule, you need to use different entity functions (For Scope, For All Scope and Exists Scope) that specify the 'scope' of the entities.

The concept of scope in rules

To fully understand cross entity reasoning, it is important to understand the concept of scoping in relation to a rule. The Word compiler processes a rule in a top-to-bottom fashion. The top (conclusion) line is evaluated, then the second line, and so on. For a particular line in a rule, the scope is the set of entity instances that have been previously mentioned in parent rule lines. These are the only entity instances that reasoning can be done on. In most cases, the conclusion line introduces a single entity instance into scope. (The exception to this is a membership conclusion which introduces two entities into scope - the source of the inferred relationship and the target of the inferred relationship. See Write rules that infer relationships and entities for more information). Once an entity instance has been introduced to the scope, it can be reasoned with in all rule lines that are children of the line that introduced it. The global entity is always available to the rule scope, as are the parent entities in the entity's containment relationship.

The For Scope, For All Scope and Exists Scope functions are used as scoping statements to cross a relationship and thereby introduce the target of the relationship into scope.

An example of cross entity reasoning

This example is based on a telecommunications retail style model where a customer entity has a one-to-one relationship to a plan entity (the customer's current plan) which has a many-to-many relationship to specific products (the plan's products). That is:

the customer -> the customer's current plan (one-to-one) -> the plan -> the plan's products (many-to-many) -> the product

You could then have the following rule which uses the For Scope and Exists Scope entity functions:

 

the customer has incompatible products if

ForScope(the customer's current plan)

ExistsScope(the plan's products)

the plan's network <> the product's network

 

In the example above, the initial scope for this rule is "the customer", established by the conclusion on line 1. "The plan" was brought into the scope in line 2 by crossing the relationship "the customer's current plan", and "the product" was brought into the scope in line 3 by crossing the relationship "the plan's products". Finally in line 4 we compare an attribute of "the plan" with and attribute of "the product". Both entities are now in scope so this reasoning is possible.

 

An example of the For All Scope function using the same data model would be:

 

the customer is satisfied if

in the case of the customer's current plan

ForAllScope(the plan's products)

the product's rating = "AAA"

Use relationship membership as a rule input

Relationship membership can be used as a rule input by creating a membership statement and using it as a condition in a rule. A membership statement always reasons against the source entity and the target entity. The membership statement will be true if the target entity is the target of the relationship for the source entity. A membership statement can be used for any type of relationship.

 

A membership statement used as a condition takes one of the following forms:

 

In the example rule below, a membership statement is used as a condition to determine if a dog is happy based on whether it is a member of the person's favorite dogs.

 

the dog is happy if

ForScope(the dog's owner)

IsMemberOf(the dog, the person's favorite dogs)

 

Both entities (ie the source entity and the target entity) must be brought into the scope of the rule, otherwise the compiler will attempt to create an attribute "<target entity> is a member of <relationship text>".

NOTES:

  1. A membership statement that is used as a condition cannot have any children under it in that rule. It must, however, be proved by another rule. For example, the membership statement in the example above must be proved by another rule (eg "the dog is a member of the person's favorite dogs if the dog is well-behaved").
  2. A membership statement can true when the relationship is partially known. So long as it is known that the entity instance in question is a member of the relationship, the membership statement will return as true.

Remove ambiguity when reasoning about more than one instance of the same entity

When you want to reason with more than one instance of the same entity, it can become ambiguous as to which entity instances your rules are referring to. You can use an alias for the desired entity instances in your rules to remove this ambiguity.

Aliasing allows you to use an alternative name to refer to an entity instance. An alias can be used in a conclusion or condition, and its use is limited to that particular conclusion or condition. NOTE: Once an alias is defined it must be used in place of the regular name for the associated entity, otherwise an error will occur. Also note that the name of an entity cannot be used as an alias.

An alias can be used in two places to resolve ambiguity: in a scope entity function, and in a relationship conclusion.

Using an alias in a scoped entity function

In a scoped entity function (ie the functions For Scope, For All Scope and Exists Scope) an alias can be assigned to the target entity instance when the entity is already in the rule scope and you need to discriminate between those entities instances.
For example, if you wanted to compare two person entity instances through the relationship "the person’s spouse", you could define an alias to the target of "the person’s spouse". Once the alias is defined, you can then refer to attributes of the target instance as "the spouse":

 

the person has the highest taxable income if

ForScope(the person's spouse, the spouse)

the person's income > the spouse's income

 

Note that in this rule, you only need to add an attribute for 'the person's income', not for 'the spouse's income', as the compiler knows that any attributes using the alias text belong to the associated entity (in this case 'the person').

If you want to compare entity instances in a relationship that does not include the global entity (eg from 'the toy' to 'the child'), you need to traverse up and down the relationship as shown in the example below:

 

the toy is the same type as another owned by the same child if

ForScope(the child who owns the toy)

ExistsScope(the child's toys, the other toy)

the toy type = the other toy type and

the toy name <> the other toy name

Using an alias in a relationship conclusion

In a relationship conclusion (ie the function Is Member Of) an alias can be assigned to the target entity instance in the membership statement. This is useful for situations where the source and the target of the relationship are the same entity. For example, in the rule below, "the person's workplace" is a text attribute in the entity "the person", and "the person's co-workers" is a many-to-many relationship whose source is "the person", and whose target is also "the person":


the person (the colleague) is a member of the person's co-workers if

the person's workplace = the colleague's workplace

Compare instances of the same entity

When you are reasoning with more than one instance of the same entity, you may want to compare attribute values across entity instances. The comparison of the entity attribute values does not differentiate whether the target entity instance is the same as the one in which the rule is operating. This can result in the attribute comparisons being satisfied with values of the same entity instance, which may not be the logic that you wish to represent in your rules.

The InstanceEquals and InstanceNotEquals functions allow you to compare the entity instances themselves, so you can avoid this situation.

For example, the following rule examines instances of the employee entity to see whether any employee ID is used by multiple employees:

 

the employee has a conflicting ID if

ExistsScope(the employees, the other employee)

the employee's ID = the other employee's ID and

InstanceNotEquals(the employee, the other employee)

 

The ID for each employee entity instance is compared against all employee IDs, one of which will be a match between the same entity instance. To eliminate this match from the concluded outcome of the rule, the InstanceNotEquals function is used to ensure only ID matches from different entity instances cause the rule to evaluate to true.

 

See also: